/** @jsxImportSource @emotion/react */
//import { jsx,  } from "@emotion/react";
// import {  css } from "@emotion/react";
// import * as React from "react";
//import { Layer } from "./Layer";
// import PropTypes from "prop-types";
//import { useTheme } from "./Theme/Providers";

//报表，打印的表格：　从sancho拷贝来，深度定做。
import {Layer, useTheme,} from "customize-easy-ui-component";


import {jsx,  css } from "@emotion/react";
import * as React from "react";
// import { Layer } from "./Layer";
import PropTypes from "prop-types";
// import { useTheme } from "./Theme/Providers";
import {ElementType} from "react";
// import theme from "./Theme";


type SectionTypeVariants = "TableHead" | "TableBody";

interface TableSectionContextType {
    type: SectionTypeVariants;
    lrBoder?: boolean;
}

//没有对外输出TableSectionContext的；无法import {TableSectionContext} from "customize-easy-ui-component";
const TableSectionContext = React.createContext<TableSectionContextType>({
    type: "TableHead"
});

//旧版本的TableOld才需要使用到的 context变量； 新版本已经改成参数适应;
const TableContext = React.createContext({ fixed: false });

/**
 * A Table provides a useful abstraction for managing rows and columns.
 */

interface TableProps extends React.HTMLAttributes<HTMLTableElement> {
    /** An optional minimum width for table content.
     * 配置表格的最小宽度，小于它就启用水平滚动条。 举例：minWidth=css 单位。
     *  */
    minWidth?: string;
    /** An optional array of fixed layout widths for each column
     * 非打印场景的必须看fixed； 打印场景优先使用printColWidth；若这两者都没定义那就是系统自动的 走了浏览器默认机制。
     * 百分比% 和数值px两种形式。 举例：fixed={["8%","23%","%","12%"] }  printColWidth={["60","156","700","80"]}
     * */
    fixed?: string[];
    //打印场景才采用的： 敲定的列宽on printer case,set just as fixed  above; 3种形式[pixels, %, relative_length%]; pixels单位是px;
    /**允许打印时刻特别调整各列的宽度比例
     * 就算不是百分比的配置 也即用pixels的：最后也是同义转换百分比处理
     * */
    printColWidth?: string[];
    //为了处理这个毛病：用100%宽度+打印时若没有勾选页眉页脚的，可能右边表格边线被裁减不见。Chrome版本116.0.5845.118正常。而117.0.5938.92版本Chrome有问题不勾选页眉页脚的就被截切。
    // prevPrune?: boolean; 改成了用全局的<Global styles={{ body: { margin: 0, "@media print": { margin: '0 1px 0 0'},},样式来解决这个BUG问题了。
    //约定打印的合计总宽度= px单位的，优先于printColWidth，打印各列宽度比例按照printColWidth比例映射，或者没有printColWidth就按照fixed比例映射；
    // agptWidth?: number;
    //嵌套表格，宽度被父辈Table做了约定的，并且要求自动和父辈同宽度的合并边线的。
    // nested?: boolean;
}


//等待删除 代码
//@Deprecated
const TableOld: React.FunctionComponent<TableProps> = ({
                                                           children,
                                                           minWidth,
                                                           fixed,
                                                           ...other
                                                       }) => {
    const theme = useTheme();

    return (
        <div
            css={{
                width: "100%",
                display: "block",
                overflowX: minWidth ? "auto" : "initial"
            }}
        >
            <table
                css={{
                    borderSpacing: 0,
                    borderCollapse: "separate",
                    width: "100%",
                    fontFamily: theme.fonts.base,
                    WebkitAppearance: "none",
                    WebkitFontSmoothing: "antialiased",
                    display: "table",
                    minWidth,
                    tableLayout: fixed ? "fixed" : undefined
                }}
                {...other}
            >
                {fixed && (
                    <colgroup>
                        {fixed.map((width, i) => {
                            return <col key={i} width={width} />;
                        })}
                    </colgroup>
                )}
                <TableContext.Provider value={{ fixed: fixed ? true : false }}>
                    {children}
                </TableContext.Provider>
            </table>
        </div>
    );
};


type  LayoutValType= "fixed" | undefined;
type  ColgroupWidthType= string[] | number[];

/**
 支持打印自适应，支持手机自适应。 Table不适合小屏幕和列数较多的字段长度不统一可能较长的这些情形。
 @param fixed:非打印的布局各列尺寸设置，一般是百分比比例。 若fixed不设置会自动调整的。
 @param printColWidth:真实打印或打印预览情况的布局各列尺寸，一般是px数值。合计一般：A4竖版就是合计718px，超过了会自动缩小字体。
 若printColWidth没必要一定要准确配置的呢？嵌套表格的上一级宽度已经是父辈Table做了约定的？
 @param agptWidth: 约定打印的合计总宽度，优先于printColWidth，打印各列宽度比例按照printColWidth比例映射，或者没有printColWidth就按照fixed比例映射；
  对于A4 竖版打印 windows chrome正好 718 px的不会缩小。
 嵌套在内部的表格 设置agptWidth={0} 可以自适应宽度；
 @param nested:嵌套表格，宽度被父辈Table做了约定的，并且要求自动和父辈同宽度的合并边线的。agptWidth若没有设置的就按比例分配100%宽度。
 */
export const Table: React.FunctionComponent<TableProps> = ({
                                                               children,
                                                               minWidth,
                                                               fixed,
                                                               printColWidth,
                                                               ...other
                                                           }) => {
    const theme = useTheme();
    const [printLayout, printFinWid] =React.useMemo(() => {
        let config=printColWidth? printColWidth : fixed;
        if(!config)  return [undefined, undefined];
        //2种形式[pixels, %, relative_length%]不能混和配置的吧；
        let percent=false;
        let pcs=config.map((width, i) => {
            if(!percent && width.endsWith('%'))   percent=true;
            const strnum = width.replace(/[%]/g, '');
            return Number(strnum);
        });
        let remain=-1;   //配置数组当中唯一一个的 %位置点 的索引；
        pcs.forEach((wd, index, array) => {
            if(wd<=0){
                array[index]=0;
                if(percent && array[index]===0)  remain=index;
            }
        });
        let totals= pcs.reduce(function (total, value) {
            return total + value;
        }, 0);
        if(percent && remain>=0){
            if(totals<100){
                pcs[remain]=100-totals;      //分配唯一个的 %位点
                totals=100;
            }
        }
        // if(!nested && agptWidth<=0)      //也允许agptWidth==0来纠正的
        //     return ["fixed", pcs];
        //重新计算比例：
        let finalPc=pcs.map((oldpc, i) => {
            let pctv=100*oldpc/totals;
            return `${Math.round(pctv*100)/100}%`;
                    //若不加上‘%’且也不乘以100倍数，可能导致最后一列的误差非常巨大的！！
        });
        return ["fixed", finalPc];      //嵌套 设置agptWidth={0}
      //不能用px数字直接<colgroup<col配置，列数多了就会很容易出现实际上竟然超出限制px数，导致边线会丢失。 【只好】改成百分比做法+上级来设置width: 718px;
    }, [printColWidth,fixed])  as [LayoutValType, ColgroupWidthType];

    return (
        <div
            css={{
                width: "100%",
                display: "block",
                overflowX: minWidth ? "auto" : "initial"
            }}
        >
            <table
                css={{
                    borderSpacing: 0,
                    borderCollapse: "separate",
                    width: "100%",
                    fontFamily: theme.fonts.base,
                    WebkitAppearance: "none",
                    WebkitFontSmoothing: "antialiased",
                    display: "table",
                    minWidth,
                    tableLayout: fixed ? "fixed" : undefined,
                    "@media print": {
                        tableLayout: printLayout,
                        //width: prevPrune? 'unset' : undefined, 去掉了100%页不好啊：因不能够铺满纸张的全宽度，需要非常准确的尺寸配置才行。对付浏览器的BUG？
                        //width: !nested? `${agptWidth}px` : undefined,  没必要限制死的；
                    }
                }}
                {...other}
            >
                {(printLayout && printFinWid) &&
                    <>
                        <colgroup
                            css={{
                            "@media print": {
                                display: 'none',
                            },
                        }}
                        >
                            {fixed?.map((width, i) => {
                                return <col key={i} width={width} />;
                            })}
                        </colgroup>
                        <colgroup
                            css={{
                                "@media not print": {
                                    display: 'none',
                                },
                            }}
                        >
                            {printFinWid.map((width, i) => {
                                return <col key={i} width={width} />;
                            })}
                        </colgroup>
                    </>
                }

                {children}

            </table>
        </div>
    );
};


Table.propTypes = {
    minWidth: PropTypes.string,
    fixed: PropTypes.arrayOf(PropTypes.any),
    printColWidth: PropTypes.arrayOf(PropTypes.any),
    children: PropTypes.node
};

/**
 * A TableHead is used to render column labels in a table.
 */

// type TableHeadProps = React.HTMLAttributes<HTMLTableSectionElement>;
interface TableHeadProps extends React.HTMLAttributes<HTMLTableSectionElement> {
    //手机小屏幕的情况，默认不显示左右的边框；
    lrBoder?: boolean;
}
/**就算TableBody在DOM流位置比TableHead靠前，也TableHead表现一样；多个Table嵌套的打印断页拆分的也类似会有多个TableHead在页首部处留存。
 * */
export function TableHead({ lrBoder,children, ...other }: TableHeadProps) {
    return (
        <thead
            css={{
                display: "table-header-group"
            }}
            {...other}
        >
        <TableSectionContext.Provider value={{ type: "TableHead",
            lrBoder,
        }}>
            {children}
        </TableSectionContext.Provider>
        </thead>
    );
}

interface TableRowProps extends React.HTMLAttributes<HTMLTableRowElement> {
    /** A callback when a row is selected */
    onClick?: () => void;
}

export const TableRow: React.FunctionComponent<TableRowProps> = ({
                                                                     onClick,
                                                                     children,
                                                                     ...other
                                                                 }) => {
    const theme = useTheme();
    const { type: tableSectionType } = React.useContext(TableSectionContext);

    const buttonProps = onClick
        ? {
            role: "button",
            tabIndex: 0
        }
        : {};

    return (
        <tr
            onClick={onClick}
            css={{
                height: tableSectionType === "TableHead" ? "31px" : "49px",
                display: "table-row",
                outline: "none",
                verticalAlign: "middle",
                cursor: onClick ? "pointer" : "default",
                ":hover": {
                    background: onClick ? theme.colors.background.tint1 : "none"
                }
            }}
            {...buttonProps}
            {...other}
        >
            {children}
        </tr>
    );
};

TableRow.propTypes = {
    onClick: PropTypes.func,
    children: PropTypes.node
};

/**
 * Cell TableCell, used for both <td> and <th> elements.
 * textAlign: "justify" 导致字间距自动变大，感觉不规整，不如textAlign: "left"。
 */

const tableCellAlignments = {
    right: css({
        textAlign: "right",
        flexDirection: "row-reverse"
    }),
    left: css({
        textAlign: "left"
    }),
    center: css({
        textAlign: "center"
    }),
    justify: css({
        textAlign: "justify"
    })
};

type AlignCellType = "right" | "left" | "center" | "justify";

type tableCellVariants = "head" | "body";

type TableCellBaseProps = React.ThHTMLAttributes<HTMLTableHeaderCellElement> &
    React.TdHTMLAttributes<HTMLTableDataCellElement>;

interface TableCellProps extends TableCellBaseProps {
    align?: AlignCellType;
    //align?: keyof typeof tableCellAlignments;
    variant?: tableCellVariants;
    ellipsis?: boolean;
    component?: React.ElementType<TableCellBaseProps>;
    /**是否<td><th>在打印之中，遇到了分页位置应该允许断开。浏览器原先默认是断开的。这里改成默认不能拆分开的。
     * split=true就是允许打印拆分断开。
     * */
    split?: boolean;
}

/**
 * 旧版本的Cell组件，新版本改用Cell; 两个版本的样式不一样
 */
export const TableCell: React.FunctionComponent<TableCellProps> = ({
                                                                       align = "left",
                                                                       variant,
                                                                       component,
                                                                       ellipsis,
                                                                       children,
                                                                       ...other
                                                                   }) => {
    const theme = useTheme();
    const { type: tableSectionType } = React.useContext(TableSectionContext);

    const Component =
        component || (tableSectionType === "TableHead" ? "th" : "td");

    const type = variant || (tableSectionType === "TableHead" ? "head" : "body");

    return (
        <Component
            css={[
                {
                    zIndex: 4,
                    position: "relative",
                    borderBottom: "1px solid",
                    borderColor:
                        tableSectionType === "TableBody"
                            ? theme.colors.border.muted
                            : theme.colors.border.default,
                    display: "table-cell",
                    padding: `${theme.spaces.xs} ${theme.spaces.sm}`,
                    [theme.mediaQueries.lg]: {
                        paddingLeft: theme.spaces.md,
                        paddingRight: theme.spaces.md
                    },
                    ":last-child": {
                        paddingRight: theme.spaces.md
                    }
                },
                ellipsis && {
                    whiteSpace: "nowrap",
                    textOverflow: "ellipsis",
                    overflow: "hidden"
                },
                type === "head"
                    ? {
                        fontWeight: 500,
                        fontSize: theme.fontSizes[0],
                        color: theme.colors.text.muted
                    }
                    : {
                        fontWeight: 400,
                        fontSize: theme.fontSizes[0],
                        color: theme.colors.text.default
                    },
                tableCellAlignments[align],
                {
                }
            ]}
            scope="col"
            {...other}
        >
            {children}
        </Component>
    );
};

TableCell.propTypes = {
    align: PropTypes.oneOf(["right","left","center","justify"] as AlignCellType[]),
    variant: PropTypes.oneOf(["body", "head"] as tableCellVariants[]),
    // component: PropTypes.element,
    ellipsis: PropTypes.bool,
    children: PropTypes.node
};
/*可以通过interface来约定react组件props，还有必要用react的propTypes吗？
2个会报类型错误？TableCell.propTypes {align: PropTypes.oneOf( ； component: PropTypes.elementType,}
 这个地方似乎是打包层次用到的。  报错？只好删除了。
 可以只用typescript进行验证，也可以只用prop-types进行验证，也可以两者混搭进行验证，这个并没用严格限制。
首先不管用typescript，还是prop-types，都只在开发模式下进行检查。 PropTypes是组件接收prop的约束。
*/

/**
 * 新版 TableCell 组件，支持手机上作表格形式的报告，支持打印。
 * 做报表用的样式, CCell, RCell类似 Cell,就差align格式;
 * 旧版本请用TableCell组件,两个版本的样式不一样
 * 前提：每一行的要么是td 要么是th，不要混合td和th;
 * @param split:允许打印拆分这个<td>吗？ component设置要注意 统一一行的td 要么th。
 */
export const Cell: React.FunctionComponent<TableCellProps> = ({
                                                                  align = "left",
                                                                  variant,
                                                                  component,
                                                                  ellipsis,
                                                                  children,
                                                                  split=false,
                                                                  ...other
                                                              }) => {
    const theme = useTheme();
    const { type: tableSectionType,lrBoder } = React.useContext(TableSectionContext);

    const Component =
        component || (tableSectionType === "TableHead" ? "th" : "td");

    const type = variant || (tableSectionType === "TableHead" ? "head" : "body");

    return (
        <Component
            css={[
                {
                    zIndex: 4,
                    position: "relative",
                    border: "1px solid",
                    display: "table-cell",
                    padding: `${theme.spaces.xs} ${theme.spaces.xs}`,
                    wordBreak: 'break-word',
                },
                ellipsis && {
                    whiteSpace: "nowrap",
                    textOverflow: "ellipsis",
                    overflow: "hidden"
                },
                type === "head"
                    ? {
                        fontWeight: 500,
                        fontSize: theme.fontSizes[0],
                        color: theme.colors.text.muted
                    }
                    : {
                        fontWeight: 400,
                        fontSize: theme.fontSizes[0],
                        color: theme.colors.text.default
                    },
                tableCellAlignments[align],
                lrBoder? {} :
                    {
                        [theme.mediaQueries.phone]: {
                            ":first-of-type": {
                                borderLeft: "none"       //每一行tr底下要么是td要么是th不要混合td和th;
                            },
                            ":last-of-type": {
                                borderRight: "none"
                            }
                        }
                    },
                {
                    "@media print": {
                        pageBreakInside: split? undefined : 'avoid',
                    }
                }
            ]}
            scope="col"
            {...other}
        >
            {children}
        </Component>
    );
};


/**
 * TableBody - indicates the body (and scrollable) portion of our table.
 */

// type TableBodyProps = React.HTMLAttributes<HTMLTableSectionElement>;
interface TableBodyProps extends React.HTMLAttributes<HTMLTableSectionElement> {
    //手机小屏幕的情况，默认不显示左右的边框；默认的在手机屏幕最左边和最右边的边框被省略去了。设置lrBoder=true恢复显示。
    lrBoder?: boolean;
}
export function TableBody({ lrBoder,children, ...other }: TableBodyProps) {
    return (
        <tbody
            css={{
                display: "table-row-group"
            }}
            {...other}
        >
        <TableSectionContext.Provider value={{ type: "TableBody",
            lrBoder,
        }}>
            {children}
        </TableSectionContext.Provider>
        </tbody>
    );
}

/**
 * An ExpandingRow displays additional content about the row when clicked.
 */

interface ExpandingRowProps {
    /** The expanded content to show when the user selects the row */
    content: (close: () => void) => React.ReactNode | React.ReactNode;
    children: React.ReactNode;
}

export const ExpandingRow: React.FunctionComponent<ExpandingRowProps> = ({
                                                                             content,
                                                                             children
                                                                         }) => {
    const theme = useTheme();
    const [selected, setSelected] = React.useState(false);

    function close() {
        setSelected(false);
    }

    function open() {
        setSelected(true);
    }

    return (
        <TableBody>
            <TableRow onClick={open}>{children}</TableRow>
            {selected && (
                <tr css={{ display: "table-row", height: "100px" }}>
                    <td
                        colSpan={React.Children.count(children)}
                        css={{
                            borderBottom: 0,
                            width: "inherit",
                            padding: 0,
                            position: "relative"
                        }}
                    >
                        <div
                            css={{
                                zIndex: 3,
                                width: "inherit",
                                position: "relative",
                                paddingBottom: "24px"
                            }}
                        >
                            <div
                                css={{
                                    position: "relative",
                                    whiteSpace: "normal",
                                    height: "auto",
                                    display: "block",
                                    paddingTop: "24px"
                                }}
                            >
                                {typeof content === "function" ? content(close) : content}
                            </div>
                        </div>
                        <Layer
                            css={{
                                position: "absolute",
                                top: "-49px",
                                left: "-16px",
                                right: "-16px",
                                borderRadius: theme.radii.md,
                                bottom: 0,
                                zIndex: 2
                            }}
                        >
                            {null}
                        </Layer>
                    </td>
                </tr>
            )}
        </TableBody>
    );
};

//被删除的部分 xxx.propTypes = {  };  是和rollup.js相关，一个模块打包工具/发布工具库，使用ES6的模块标准。

ExpandingRow.propTypes = {
    //content: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
    children: PropTypes.node
};


/**
 大量重复的组件标签，简化: CCell代表居中显示的Cell
 */
export const CCell: React.FunctionComponent<TableCellProps> =
    (
        {
            align = "center",
            variant,
            component,
            ellipsis,
            children,
            ...other
        }) =>
    {

        return (
            Cell({
                align,
                variant,
                component,
                ellipsis,
                children,
                ...other
            })
        );
    };


/**做点简化，免得看起来是一大堆重复性质代码：
 * 代表靠右边 显示的Cell
 */
export const RCell: React.FunctionComponent<TableCellProps> =
    (
        {
            align = "right",
            variant,
            component,
            ellipsis,
            children,
            ...other
        }) =>
    {

        return (
            Cell({
                align,
                variant,
                component,
                ellipsis,
                children,
                ...other
            })
        );
    };


//但@emotion会报错的：pseudo class ":first-child" is potentially unsafe when doing server-side rendering. Try changing it to ":first-of-type"；
